package bll

import (
	"context"
	"encoding/json"
	"fmt"
	"go-micro.dev/v4/broker"
	"gorm.io/gorm"
	log "manager/collector/logger"
	"manager/errors"
	"manager/utils"

	"manager/event"
	"manager/model"
	"manager/model/entity"
	"manager/store"
	"manager/store/postgres"
	"time"

	"manager/auth"
)

type userBikeSetting struct {
	iUserBikeSetting store.IUserBikeSetting
}

// EBikeBindPayload TODO 对老代码临时添加的逻辑
type EBikeBindPayload struct {
	UserId  uint `json:"user_id"`  // 用户ID
	EBikeId uint `json:"ebike_id"` // 电车ID
	Bind    bool `json:"bind"`     // 是否是绑定，true为绑定，false为解绑
}

var UserBikeSetting = &userBikeSetting{
	iUserBikeSetting: postgres.UserBikeSetting,
}

func (a *userBikeSetting) init() func() {
	return func() {}
}

func (a *userBikeSetting) onEvent(data *event.Data) {
	if data == nil || (data.Type != event.Event_Bind_Bike && data.Type != event.Event_UnBind_Bike) {
		return
	}

	log.Info("---------------- userBikeSetting onEvent data:", utils.ToJsonString(data))

	// 车辆绑定
	if event.Event_Bind_Bike == data.Type {
		// 解析参数
		obj := data.Data.(*event.BindBike)
		if obj == nil {
			log.Error("userBikeSetting onEvent err")
			return
		}

		// 参数校验
		if obj.BikeId == 0 || obj.UserId == 0 {
			log.Errorf("userBikeSetting onEvent params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}

		// TODO 对老代码临时添加的逻辑，待后期修改
		payload := EBikeBindPayload{
			UserId:  uint(obj.UserId),
			EBikeId: uint(obj.BikeId),
			Bind:    true,
		}
		payloadBytes, _ := json.Marshal(payload)
		publisher.Publish("smartemc.ebike.bind", &broker.Message{
			Header: nil,
			Body:   payloadBytes,
		})

		// 权限校验
		if !UserEbike.IsUserBindBike(obj.UserId, obj.BikeId) {
			return
		}

		// 查询记录
		total, _, _ := a.iUserBikeSetting.List(context.Background(), &model.UserBikeSettingListRequest{
			Index:   1,
			Size:    1,
			UserId:  &obj.UserId,
			EbikeId: &obj.BikeId,
		})

		if total > 0 {
			return
		}
		a.createRecode(obj.UserId, obj.BikeId)

	}

	// 车辆解绑
	if event.Event_UnBind_Bike == data.Type {
		// 解析参数
		obj := data.Data.(*event.UnBindBike)
		if obj == nil {
			log.Error("userBikeSetting onEvent err")
			return
		}

		// 参数校验
		if obj.BikeId == 0 || obj.UserId == 0 {
			log.Errorf("userBikeSetting onEvent params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}
		// TODO 对老代码临时添加的逻辑，待后期修改
		payload := EBikeBindPayload{
			UserId:  uint(obj.UserId),
			EBikeId: uint(obj.BikeId),
			Bind:    false,
		}
		payloadBytes, _ := json.Marshal(payload)
		publisher.Publish("smartemc.ebike.bind", &broker.Message{
			Header: nil,
			Body:   payloadBytes,
		})

		// 查找绑定记录
		bikeInfo, err := a.Find(context.Background(), &model.UserBikeSettingInfoRequest{
			UserId:  &obj.UserId,
			EbikeId: &obj.BikeId,
		})

		if err != nil {
			log.Errorf("userBikeSetting onEvent Event_UnBind_Bike find err:%v", err)
			return
		}

		// 删除绑定记录
		err = a.Delete(context.Background(), &model.UserBikeSettingDeleteRequest{Id: bikeInfo.Id})
		if err != nil {
			log.Errorf("userBikeSetting onEvent Event_UnBind_Bike Delete err:%v", err)
			return
		}
	}

}

// Create 创建
func (a *userBikeSetting) Create(ctx context.Context, in *model.UserBikeSettingCreateRequest) error {
	var (
		err error
	)

	// 获取用户Id
	if in.UserId == 0 {
		in.UserId, _ = auth.ContextUserID(ctx)
	}

	if in.UserId == 0 || in.EbikeId == 0 {
		return errors.ParameterErr.Error()
	}

	// todo:查看车辆、用户是否存在
	if !UserEbike.IsUserBindBike(in.UserId, in.EbikeId) {
		return errors.New("user not own the bike")
	}

	// todo: 查看是否创建过设置
	settings, err := a.iUserBikeSetting.Find(ctx, &model.UserBikeSettingInfoRequest{
		UserId:  &in.UserId,
		EbikeId: &in.EbikeId,
	})

	if settings != nil && err == nil {
		log.Warnf("userBikeSetting Create recode exist UserId:%v BikeId:%v", in.UserId, in.EbikeId)
		return nil
	}

	// 构建创建现场数据
	c := buildUserBikeSetting(in)
	_, err = a.iUserBikeSetting.Create(ctx, c)
	return err
}

// Update 更新
func (a *userBikeSetting) Update(ctx context.Context, in *model.UserBikeSettingUpdateRequest) error {
	var (
		dict = make(map[string]interface{})
	)

	updateAt := time.Now().Unix()
	in.UpdatedAt = &updateAt

	if in.EbikeId != nil {
		dict["ebike_id"] = in.EbikeId

		userId, _ := auth.ContextUserID(ctx)
		dict["user_id"] = &userId

		// 用户车辆校验
		if !UserEbike.IsUserBindBike(userId, *in.EbikeId) {
			return fmt.Errorf("bike is not yourself")
		}

		// todo: 临时这么设计，查询不存在的时候创建设置
		_, err := a.iUserBikeSetting.Find(ctx, &model.UserBikeSettingInfoRequest{
			UserId:  &userId,
			EbikeId: in.EbikeId,
		})

		if err != nil && err == gorm.ErrRecordNotFound {
			// 发送车辆绑定车主事件
			a.createRecode(userId, *in.EbikeId)
		}
	}

	if in.EbikeImage != nil {
		dict["ebike_image"] = in.EbikeImage
	}

	if in.EbikeName != nil {
		dict["ebike_name"] = in.EbikeName
	}

	if in.UpdatedAt != nil {
		dict["updated_at"] = in.UpdatedAt
	}

	//  查看是否存在相同名称的记录
	info, _ := postgres.UserBikeSetting.Find(ctx, &model.UserBikeSettingInfoRequest{
		UserId:    in.UserId,
		EbikeName: in.EbikeName,
	})

	// 如果存在相同名称的记录，且id不相同，则不修改
	if in.Id > 0 && info.Id == in.Id {
		return nil
	}

	if info.Id > 0 {
		return errors.New("bike name exist")
	}

	// do other update here

	return a.iUserBikeSetting.Update(ctx, in.Id, dict)
}

// Delete 删除
func (a *userBikeSetting) Delete(ctx context.Context, in *model.UserBikeSettingDeleteRequest) error {
	return a.iUserBikeSetting.Delete(ctx, in.Id)
}

// List 列表查询
func (a *userBikeSetting) List(ctx context.Context, in *model.UserBikeSettingListRequest) (*model.UserBikeSettingListResponse, error) {
	var (
		err   error
		total int
		list  []*entity.UserBikeSetting
		out   = &model.UserBikeSettingListResponse{}
	)

	userId, _ := auth.ContextUserID(ctx)
	// 权限校验
	if !UserEbike.IsUserBindBike(userId, *in.EbikeId) {
		return nil, fmt.Errorf("您不在预绑定列表中，无法绑定此车辆")
	}
	in.UserId = &userId

	// todo: 检查车辆信息是否合法
	if !Ebike.IsValid(*in.EbikeId) {
		return nil, errors.EbikeNotExist.Error()
	}

	// 查看记录是否存在
	if total, list, err = a.iUserBikeSetting.List(ctx, in); err != nil {
		return nil, err
	}

	// todo: 临时这么设计，查询不存在的时候创建设置
	if total == 0 {
		// 发送车辆绑定车主事件
		a.createRecode(userId, *in.EbikeId)

		// 再次查询
		if total, list, err = a.iUserBikeSetting.List(ctx, in); err != nil {
			return nil, err
		}
	}

	out.Total = total
	out.List = model.UserBikeSettingsEntityToDto(list)

	return out, nil
}

// Find 列表查询
func (a *userBikeSetting) Find(ctx context.Context, in *model.UserBikeSettingInfoRequest) (*model.UserBikeSettingInfo, error) {
	var (
		err  error
		data *entity.UserBikeSetting
		out  = &model.UserBikeSettingInfo{}
	)

	if *in.UserId == 0 {
		userId, _ := auth.ContextUserID(ctx)
		in.UserId = &userId
	}

	if data, err = a.iUserBikeSetting.Find(ctx, in); err != nil {
		return nil, err
	}

	out = model.UserBikeSettingEntityToDto(data)
	return out, nil
}

// buildUserBikeSetting 构建创建数据现场
func buildUserBikeSetting(in *model.UserBikeSettingCreateRequest) *entity.UserBikeSetting {
	// todo: check the entity is required
	return &entity.UserBikeSetting{

		UserId: in.UserId,

		EbikeId: in.EbikeId,

		EbikeImage: in.EbikeImage,

		EbikeName: in.EbikeName,

		CreatedAt: time.Now().Unix(),

		UpdatedAt: time.Now().Unix(),
	}
}

// 创建记录
func (a *userBikeSetting) createRecode(userId, bikeId int64) {
	// 获取车辆信息
	bikeInfo, err := postgres.Ebike.Find(context.Background(), bikeId)
	if err != nil {
		log.Errorf("userBikeSetting onEvent Ebikes error userId:%v bikeId:%v", userId, bikeId)
		return
	}

	// 获取车辆型号
	bikeType, err := postgres.EbikeType.Find(bikeInfo.TypeID)
	if err != nil {
		log.Errorf("userBikeSetting onEvent EbikeType error userId:%v bikeId:%v", userId, bikeId)
		return
	}

	// 车辆图片
	bikeImage := ""
	if len(bikeType.ImagePath) > 0 {
		bikeImage = bikeType.ImagePath[0]
	}

	// 创建车辆默认配置
	if err = a.Create(context.Background(), &model.UserBikeSettingCreateRequest{
		UserId:     userId,
		EbikeId:    bikeId,
		EbikeImage: bikeImage,
		EbikeName:  bikeInfo.Name,
		UpdatedAt:  time.Now().Unix(),
	}); err != nil {
		log.Errorf("setting onEvent Create default setting error userId:%v bikeId:%v", userId, bikeId)
		return
	}
}
